};
struct xen_ia64_privcmd_vma {
+ int is_privcmd_mmapped;
struct xen_ia64_privcmd_range* range;
unsigned long num_entries;
static void
xen_ia64_privcmd_vma_open(struct vm_area_struct* vma)
{
+ struct xen_ia64_privcmd_vma* old_privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
struct xen_ia64_privcmd_vma* privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
atomic_inc(&privcmd_range->ref_count);
// vm_op->open() can't fail.
privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL | __GFP_NOFAIL);
+ // copy original value if necessary
+ privcmd_vma->is_privcmd_mmapped = old_privcmd_vma->is_privcmd_mmapped;
__xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range);
}
}
}
+int
+privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
+{
+ struct xen_ia64_privcmd_vma* privcmd_vma =
+ (struct xen_ia64_privcmd_vma *)vma->vm_private_data;
+ return (xchg(&privcmd_vma->is_privcmd_mmapped, 1) == 0);
+}
+
int
privcmd_mmap(struct file * file, struct vm_area_struct * vma)
{
if (privcmd_vma == NULL) {
goto out_enomem1;
}
+ privcmd_vma->is_privcmd_mmapped = 0;
+
res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res == NULL) {
goto out_enomem1;
static struct proc_dir_entry *privcmd_intf;
static struct proc_dir_entry *capabilities_intf;
-static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
-{
#ifndef HAVE_ARCH_PRIVCMD_MMAP
- if (xchg(&vma->vm_private_data, (void *)1) != NULL)
- return 0;
+static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
#endif
- return 1;
-}
static int privcmd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
return 0;
}
+
+static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
+{
+ return (xchg(&vma->vm_private_data, (void *)1) == NULL);
+}
#endif
static struct file_operations privcmd_file_ops = {